// DecisionContext.java
package org.zjx.core;

import lombok.Getter;
import org.zjx.core.state.StateAccessor;
import org.zjx.core.state.StateComponent;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 决策上下文 - 封装决策过程中需要的所有上下文信息
 *
 * 这个类提供了访问游戏状态、本地参数和调用栈的能力，
 * 是决策节点执行时的环境上下文。
 */
@Getter
public class DecisionContext {
    // 上下文唯一标识符
    private final String contextId;
    // 状态访问器，提供对游戏状态的访问
    private final StateAccessor stateAccessor;
    // 本地参数映射，存储决策过程中使用的临时参数
    private final Map<String, Object> localParams;
    // 调用栈，记录决策节点的执行路径
    private final Deque<DecisionStack.Frame> callStack;

    /**
     * 使用随机UUID构造决策上下文
     *
     * @param stateAccessor 状态访问器
     */
    public DecisionContext(StateAccessor stateAccessor) {
        this(UUID.randomUUID().toString(), stateAccessor, new ConcurrentHashMap<>(), new ArrayDeque<>());
    }

    /**
     * 使用指定本地参数构造决策上下文
     *
     * @param stateAccessor 状态访问器
     * @param localParams 本地参数映射
     */
    public DecisionContext(StateAccessor stateAccessor, Map<String, Object> localParams) {
        this(UUID.randomUUID().toString(), stateAccessor, localParams, new ArrayDeque<>());
    }

    /**
     * 使用指定本地参数和调用栈构造决策上下文
     *
     * @param stateAccessor 状态访问器
     * @param localParams 本地参数映射
     * @param callStack 调用栈
     */
    public DecisionContext(StateAccessor stateAccessor, Map<String, Object> localParams, Deque<DecisionStack.Frame> callStack) {
        this(UUID.randomUUID().toString(), stateAccessor, localParams, callStack);
    }

    /**
     * 完整构造函数
     *
     * @param contextId 上下文ID
     * @param stateAccessor 状态访问器
     * @param localParams 本地参数映射
     * @param callStack 调用栈
     */
    public DecisionContext(String contextId, StateAccessor stateAccessor,
                           Map<String, Object> localParams, Deque<DecisionStack.Frame> callStack) {
        this.contextId = contextId;
        this.stateAccessor = stateAccessor;
        // 使用线程安全的ConcurrentHashMap包装传入的参数映射
        this.localParams = new ConcurrentHashMap<>(localParams);
        // 使用传入的调用栈(可能为null)
        this.callStack = new ArrayDeque<>(callStack);
    }

    /**
     * 获取状态组件(必须存在)
     *
     * @param <T> 组件类型
     * @param type 组件类对象
     * @return 找到的组件实例
     * @throws IllegalStateException 当组件不存在时抛出
     */
    public <T extends StateComponent> T requireComponent(Class<T> type) {
        return stateAccessor.requireComponent(type);
    }

    /**
     * 获取状态组件(可选)
     *
     * @param <T> 组件类型
     * @param type 组件类对象
     * @return 包含组件的Optional，如果不存在则为空
     */
    public <T extends StateComponent> Optional<T> getComponent(Class<T> type) {
        return stateAccessor.getComponent(type);
    }

    /**
     * 获取上下文参数(可选)
     *
     * @param <T> 参数类型
     * @param key 参数键
     * @return 包含参数的Optional，如果不存在则为空
     */
    @SuppressWarnings("unchecked")
    public <T> Optional<T> getParam(String key) {
        return Optional.ofNullable((T) localParams.get(key));
    }

    /**
     * 获取上下文参数(必须存在)
     *
     * @param key 参数键
     * @return 参数值
     * @throws IllegalStateException 当参数不存在时抛出
     */
    public Object requireParam(String key) {
        return getParam(key).orElseThrow(() ->
                new IllegalStateException("Missing required parameter: " + key));
    }
}